#include <iomanip>
#include <mutex>
#include <sstream>
#include <stdio.h>

#include <iostream>

#include "rknn_api.h"

#include "common.hpp"
#include "preprocess.h"

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include "rkpt.hpp"

// 添加FP16转换函数声明
static float fp16_to_fp32(uint16_t fp16_val) {
    // 按IEEE-754标准从FP16转换到FP32
    uint32_t sign = (fp16_val >> 15) & 0x1;
    uint32_t exponent = (fp16_val >> 10) & 0x1F;
    uint32_t fraction = fp16_val & 0x3FF;
    
    uint32_t fp32_val;
    
    if (exponent == 0) {
        if (fraction == 0) {
            // 零值
            fp32_val = sign << 31;
        } else {
            // 非规格化数值
            int e = -14;
            while ((fraction & 0x400) == 0) {
                fraction <<= 1;
                e--;
            }
            fraction &= 0x3FF;
            exponent = e + 127;
            fp32_val = (sign << 31) | (exponent << 23) | (fraction << 13);
        }
    } else if (exponent == 0x1F) {
        // 无穷大或NaN
        fp32_val = (sign << 31) | (0xFF << 23) | (fraction << 13);
    } else {
        // 规格化数值
        exponent = exponent + (127 - 15);
        fp32_val = (sign << 31) | (exponent << 23) | (fraction << 13);
    }
    
    float result;
    memcpy(&result, &fp32_val, sizeof(result));
    return result;
}

// 获取核心数量的函数
static int get_core_num()
{
    // 默认返回0，表示使用NPU核心0
    // 可以根据实际硬件配置调整
    return 0;
}

// 打印RKNN张量的属性信息 index : 张量索引 name : 张量名称 n_dims : 维度数量 dims : 各维度大小 n_elems : 元素总数 size
// : 数据大小 w_stride : 宽度步长 size_with_stride : 包含步长的大小 fmt : 数据格式 type : 数据类型 qnt_type
// : 量化类型 zp : 零点值 scale : 缩放因子
static void dump_tensor_attr(rknn_tensor_attr *attr)
{
    std::string shape_str = attr->n_dims < 1 ? "" : std::to_string(attr->dims[0]);
    for (uint32_t i = 1; i < attr->n_dims; ++i)
    {
        shape_str += ", " + std::to_string(attr->dims[i]);
    }

    // printf("  index=%d, name=%s, n_dims=%d, dims=[%s], n_elems=%d, size=%d, w_stride = %d, size_with_stride=%d,
    // fmt=%s, "
    //        "type=%s, qnt_type=%s, "
    //        "zp=%d, scale=%f\n",
    //        attr->index, attr->name, attr->n_dims, shape_str.c_str(), attr->n_elems, attr->size, attr->w_stride,
    //        attr->size_with_stride, get_format_string(attr->fmt), get_type_string(attr->type),
    //        get_qnt_type_string(attr->qnt_type), attr->zp, attr->scale);
}

// fp : 文件指针 ofst : 偏移量 sz : 数据大小

static unsigned char *load_data(FILE *fp, size_t ofst, size_t sz)
{
    unsigned char *data;
    int ret;

    data = NULL;

    if (NULL == fp)
    {
        return NULL;
    }

    ret = fseek(fp, ofst, SEEK_SET);
    if (ret != 0)
    {
        printf("blob seek failure.\n");
        return NULL;
    }

    data = (unsigned char *)malloc(sz);
    if (data == NULL)
    {
        printf("buffer malloc failure.\n");
        return NULL;
    }
    ret = fread(data, 1, sz, fp);
    return data;
}

static unsigned char *load_model(const char *filename, int *model_size)
{
    FILE *fp;
    unsigned char *data;

    fp = fopen(filename, "rb");
    if (NULL == fp)
    {
        printf("Open file %s failed.\n", filename);
        return NULL;
    }

    fseek(fp, 0, SEEK_END);
    int size = ftell(fp);

    data = load_data(fp, 0, size);

    fclose(fp);

    *model_size = size;
    return data;
}

RkPt::RkPt(const std::string &model_path)
{
    // 初始化变量
    ret = 0;
    this->model_path = model_path;
    model_data = nullptr;
    input_attrs = nullptr;
    output_attrs = nullptr;

    // 设置推理参数
    nms_threshold = NMS_THRESH;
    box_conf_threshold = BOX_THRESH;

    // 设置输入参数 - 根据模型输入尺寸修改
    // 🔧 修正：使用与训练时一致的640x640尺寸
    width = 640;   // 宽度 - YOLOv8模型参数（与训练时一致）
    height = 640;  // 高度 - YOLOv8模型参数（修正为640）
    channel = 3;   // 通道数 - RGB
}

int RkPt::init(rknn_context *ctx_in, bool isChild)
{
    printf("创建模型: %s\n", model_path.c_str());
    int model_data_size = 0;
    model_data = load_model(model_path.c_str(), &model_data_size);
    if (model_data == NULL)
    {
        printf("Failed to load model file: %s\n", model_path.c_str());
        return -1;
    }
    printf("Model loaded successfully, size: %d bytes\n", model_data_size);

    // 模型参数复用
    if (isChild == true)
    {
        printf("Sharing weights from existing context\n");
        ret = rknn_dup_context(ctx_in, &ctx);
    }
    else
    {
        printf("Initializing new RKNN context\n");
        ret = rknn_init(&ctx, model_data, model_data_size, 0, NULL);
    }
    if (ret < 0)
    {
        printf("rknn_init error ret=%d\n", ret);
        return -1;
    }
    printf("RKNN context initialized successfully\n");

    // 设置模型绑定的核心
    printf("Setting NPU core mask...\n");
    rknn_core_mask core_mask;
    switch (get_core_num())
    {
    case 0:
        core_mask = RKNN_NPU_CORE_0;
        break;
    case 1:
        core_mask = RKNN_NPU_CORE_1;
        break;
    case 2:
        core_mask = RKNN_NPU_CORE_2;
        break;
    }
    ret = rknn_set_core_mask(ctx, core_mask);
    if (ret < 0)
    {
        printf("rknn_set_core_mask error ret=%d\n", ret);
        return -1;
    }
    printf("NPU core mask set successfully\n");

    printf("Querying SDK version...\n");
    rknn_sdk_version version;
    ret = rknn_query(ctx, RKNN_QUERY_SDK_VERSION, &version, sizeof(rknn_sdk_version));
    if (ret < 0)
    {
        printf("rknn_query SDK_VERSION error ret=%d\n", ret);
        return -1;
    }
    printf("sdk version: %s driver version: %s\n", version.api_version, version.drv_version);

    // 获取模型输入输出参数
    printf("查询RKNN输入/输出数量\n");
    ret = rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, &io_num, sizeof(io_num));
    if (ret != RKNN_SUCC)
    {
        printf("查询输入/输出数量失败！ret=%d\n", ret);
        return -1;
    }
    printf("模型输入数量: %d, 输出数量: %d\n", io_num.n_input, io_num.n_output);

    // 设置输入参数
    input_attrs = (rknn_tensor_attr *)calloc(io_num.n_input, sizeof(rknn_tensor_attr));
    for (uint32_t i = 0; i < io_num.n_input; i++)
    {
        input_attrs[i].index = i;
        ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr));
        if (ret != RKNN_SUCC)
        {
            printf("查询第 %d 个输入属性失败！ret=%d\n", i, ret);
            return -1;
        }
        printf("  输入 #%d: dims=[", i);
        for (uint32_t j = 0; j < input_attrs[i].n_dims; j++)
        {
            printf("%d", input_attrs[i].dims[j]);
            if (j < input_attrs[i].n_dims - 1) printf(", ");
        }
        printf("], 数据类型=%d, fmt=%d\n", input_attrs[i].type, input_attrs[i].fmt);
    }

    // 设置输出参数
    output_attrs = (rknn_tensor_attr *)calloc(io_num.n_output, sizeof(rknn_tensor_attr));
    for (uint32_t i = 0; i < io_num.n_output; i++)
    {
        output_attrs[i].index = i;
        ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr));
        if (ret != RKNN_SUCC)
        {
            printf("查询第 %d 个输出属性失败！ret=%d\n", i, ret);
            return -1;
        }
        printf("  输出 #%d: dims=[", i);
        for (uint32_t j = 0; j < output_attrs[i].n_dims; j++)
        {
            printf("%d", output_attrs[i].dims[j]);
            if (j < output_attrs[i].n_dims - 1) printf(", ");
        }
        printf("], 数据类型=%d, fmt=%d\n", output_attrs[i].type, output_attrs[i].fmt);
    }

    // 打印所有输入/输出张量属性
    printf("\n查询输入张量信息:\n");
    for (uint32_t i = 0; i < io_num.n_input; i++)
    {
        input_attrs[i].index = i;
        ret = rknn_query(ctx, RKNN_QUERY_INPUT_ATTR, &(input_attrs[i]), sizeof(rknn_tensor_attr));
        if (ret != RKNN_SUCC)
        {
            printf("查询第 %d 个输入属性失败！ret=%d\n", i, ret);
            return -1;
        }
        
        printf("  输入 #%d: dims=[", i);
        for (uint32_t j = 0; j < input_attrs[i].n_dims; j++)
        {
            printf("%d", input_attrs[i].dims[j]);
            if (j < input_attrs[i].n_dims - 1) printf(", ");
        }
        printf("], 数据类型=%d, fmt=%d\n", input_attrs[i].type, input_attrs[i].fmt);
    }

    printf("\n查询输出张量信息:\n");
    for (uint32_t i = 0; i < io_num.n_output; i++)
    {
        output_attrs[i].index = i;
        ret = rknn_query(ctx, RKNN_QUERY_OUTPUT_ATTR, &(output_attrs[i]), sizeof(rknn_tensor_attr));
        if (ret != RKNN_SUCC)
        {
            printf("查询第 %d 个输出属性失败！ret=%d\n", i, ret);
            return -1;
        }
        
        printf("  输出 #%d: dims=[", i);
        for (uint32_t j = 0; j < output_attrs[i].n_dims; j++)
        {
            printf("%d", output_attrs[i].dims[j]);
            if (j < output_attrs[i].n_dims - 1) printf(", ");
        }
        printf("], 数据类型=%d, fmt=%d\n", output_attrs[i].type, output_attrs[i].fmt);
    }

    // 根据输入格式解析模型输入的通道数，高度和宽度（NCHW或NHWC）
    if (input_attrs[0].fmt == RKNN_TENSOR_NCHW)
    {
        // printf("model is NCHW input fmt\n");
        channel = input_attrs[0].dims[1];
        height = input_attrs[0].dims[2];
        width = input_attrs[0].dims[3];
    }
    else
    {
        // printf("model is NHWC input fmt\n");
        height = input_attrs[0].dims[1];
        width = input_attrs[0].dims[2];
        channel = input_attrs[0].dims[3];
    }
    printf("模型输入尺寸: height=%d, width=%d, channel=%d\n", height, width, channel);

    // 【关键修复】配置输入参数 - 模型期望FP16输入，NCHW格式
    memset(inputs, 0, sizeof(inputs));
    inputs[0].index = 0;
    inputs[0].type = RKNN_TENSOR_FLOAT16;  // 修改为FP16类型以匹配模型
    inputs[0].size = width * height * channel * sizeof(uint16_t);  // FP16每个元素2字节
    inputs[0].fmt = RKNN_TENSOR_NHWC;     // 【修复】使用NHWC格式匹配模型实际输入[1,640,640,3]
    inputs[0].pass_through = 0;
    
    printf("配置输入参数: 类型=FP16, 尺寸=%dx%dx%d, 数据大小=%d bytes\n", 
           height, width, channel, inputs[0].size);

    return 0;
}

// 获取上下文
rknn_context *RkPt::get_pctx()
{
    return &ctx;
}

DetectionResultsGroup RkPt::infer(cv::Mat &orig_img, int cur_frame_id)
{
    std::lock_guard<std::mutex> lock(mtx);

    // 检查输入图像是否有效
    if (orig_img.empty())
    {
        std::cerr << "输入图像为空" << std::endl;
        DetectionResultsGroup empty_result;
        empty_result.cur_img = cv::Mat();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }

    cv::Mat img;
    cv::cvtColor(orig_img, img, cv::COLOR_BGR2RGB);
    img_width = img.cols;
    img_height = img.rows;

    BOX_RECT pads;
    memset(&pads, 0, sizeof(BOX_RECT));
    cv::Size target_size(width, height);
    cv::Mat resized_img(target_size.height, target_size.width, CV_8UC3);
    
    // 【修复】声明处理后的图像变量和静态内存缓冲区，确保在整个推理过程中有效
    cv::Mat processed_img;
    static std::vector<uint16_t> hwc_buffer;  // 静态缓冲区，存储HWC格式数据，确保内存生命周期

    // 【修复】声明并计算缩放比例，支持letterbox预处理保持宽高比
    float scale_w = (float)width / img.cols;    // width=模型输入宽度
    float scale_h = (float)height / img.rows;   // height=模型输入高度
    
    printf("输入图像尺寸: %dx%d, 目标尺寸: %dx%d, 缩放因子: w=%.3f, h=%.3f\n", 
           img.cols, img.rows, width, height, scale_w, scale_h);
    
    // 图像预处理 - 使用letterbox保持宽高比（YOLOv8标准预处理）
    if (img_width != width || img_height != height)
    {
        
        // 计算保持宽高比的统一缩放因子
        float scale = std::min(scale_w, scale_h);
        
        // 使用letterbox函数处理图像，确保正确填充
        cv::Scalar pad_color(114, 114, 114); // YOLOv8标准填充色（灰色）
        letterbox(img, resized_img, pads, scale, target_size, pad_color);
        
        // 更新缩放因子为实际使用的统一缩放因子
        scale_w = scale_h = scale;
        
        printf("letterbox预处理完成: left=%d, right=%d, top=%d, bottom=%d, scale=%.3f\n",
               pads.left, pads.right, pads.top, pads.bottom, scale);
        
        // 【关键修复】处理图像数据并转换为FP16格式
        // 步骤1: 确保数据连续性
        cv::Mat continuous_img;
        if (resized_img.isContinuous()) {
            continuous_img = resized_img.clone();
        } else {
            continuous_img = resized_img.clone();
        }
        
        // 步骤2: 转换为FP16格式 (归一化到[0,1]并转换为FP16)
        cv::Mat float_img, fp16_img;
        continuous_img.convertTo(float_img, CV_32F, 1.0/255.0);  // 归一化到[0,1]
        float_img.convertTo(fp16_img, CV_16F);  // 转换为FP16
        
        // 确保FP16图像数据连续性
        if (!fp16_img.isContinuous()) {
            fp16_img = fp16_img.clone();
        }
        
        // 【关键修复】直接使用HWC格式，无需CHW转换，匹配NHWC模型输入
        
        // 【关键修复】直接使用HWC格式，无需CHW转换，匹配NHWC模型输入
        int h = fp16_img.rows, w = fp16_img.cols;
        int total_elements = h * w * 3;
        
        // 【修复】fp16_img已经是RGB格式，无需再次转换颜色
        // 原因：输入图像在第366行已经从BGR转换为RGB，后续处理都保持RGB格式
        
        // 确保数据连续性
        if (!fp16_img.isContinuous()) {
            fp16_img = fp16_img.clone();
        }
        
        // 调整静态缓冲区大小并直接复制HWC数据
        hwc_buffer.resize(total_elements);
        uint16_t* hwc_data = hwc_buffer.data();
        
        printf("🔄 使用静态缓冲区存储HWC格式数据，总元素=%d\n", total_elements);
        printf("  数据布局: HWC (Height=%d, Width=%d, Channels=3) - RGB格式\n", h, w);
        
        // 直接复制HWC格式的数据（不需要通道分离和重排）
        memcpy(hwc_data, fp16_img.data, total_elements * sizeof(uint16_t));
        
        // 创建包装静态缓冲区的Mat
        processed_img = cv::Mat(h, w, CV_16FC3, hwc_data);
        
        printf("✅ HWC数据复制完成: 总元素=%d, 内存大小=%zu bytes\n", 
               total_elements, hwc_buffer.size() * sizeof(uint16_t));
        
        printf("✅ 数据格式：保持HWC (RGB通道顺序)，匹配NHWC模型输入\n");
        
        // 可视化处理后的图像（调试用）
        cv::Mat debug_img;
        cv::cvtColor(continuous_img, debug_img, cv::COLOR_RGB2BGR);
        cv::imshow("processed_img", debug_img);
        cv::waitKey(1);
        
        inputs[0].buf = hwc_buffer.data();  // 直接使用静态缓冲区
        
        printf("图像预处理完成(FP16-HWC): 原尺寸=%dx%dx%d, HWC张量总元素=%d, 数据类型=%d, 连续性=%s\n", 
               height, width, channel, (int)processed_img.total(),
               processed_img.type(), processed_img.isContinuous() ? "是" : "否");
        
        // 【增强调试】检查预处理后的数据有效性
        if (processed_img.type() == CV_16F) {
            uint16_t* fp16_data = (uint16_t*)processed_img.data;
            printf("前4个FP16像素值: 0x%04x 0x%04x 0x%04x 0x%04x\n",
                   fp16_data[0], fp16_data[1], fp16_data[2], fp16_data[3]);
            printf("对应浮点值: %.4f %.4f %.4f %.4f\n",
                   fp16_to_fp32(fp16_data[0]), fp16_to_fp32(fp16_data[1]),
                   fp16_to_fp32(fp16_data[2]), fp16_to_fp32(fp16_data[3]));
            
            // 【关键诊断】统计静态缓冲区中的像素值分布（HWC格式）
            float min_val = 999.0f, max_val = -999.0f, sum_val = 0.0f;
            int total_pixels = hwc_buffer.size();  // 静态缓冲区总元素数
            int sample_count = std::min(1000, (int)total_pixels);
            
            for (int i = 0; i < sample_count; i++) {
                float val = fp16_to_fp32(hwc_buffer[i]);
                if (val < min_val) min_val = val;
                if (val > max_val) max_val = val;
                sum_val += val;
            }
            
            float avg_val = sum_val / sample_count;
            printf("🔍 像素值统计(样本%d): 最小=%.4f, 最大=%.4f, 平均=%.4f\n", 
                   sample_count, min_val, max_val, avg_val);
            
            // 检查是否有异常值
            if (min_val < -1.0f || max_val > 2.0f) {
                printf("⚠️  像素值异常！期望范围[0,1]，实际[%.4f,%.4f]\n", min_val, max_val);
            } else if (avg_val < 0.01f || avg_val > 0.99f) {
                printf("⚠️  图像可能过暗(%.4f<0.01)或过亮(%.4f>0.99)\n", avg_val, avg_val);
            } else {
                printf("✅ 像素值范围正常\n");
            }
            
            // 检查是否全为0（表明预处理失败）
            bool all_zero = true;
            for (int i = 0; i < std::min(100, (int)hwc_buffer.size()); i++) {
                if (fp16_to_fp32(hwc_buffer[i]) != 0.0f) {
                    all_zero = false;
                    break;
                }
            }
            if (all_zero) {
                printf("❌ 致命错误：静态缓冲区数据全为0！\n");
            }
        }
    }
    else
    {
        // 即使尺寸匹配，也要转换为FP16格式和CHW布局
        cv::Mat continuous_img;
        if (img.isContinuous()) {
            continuous_img = img.clone();
        } else {
            continuous_img = img.clone();
        }
        
        // 转换为FP16格式
        cv::Mat float_img, fp16_img;
        continuous_img.convertTo(float_img, CV_32F, 1.0/255.0);
        float_img.convertTo(fp16_img, CV_16F);
        
        if (!fp16_img.isContinuous()) {
            fp16_img = fp16_img.clone();
        }
        
        // 【修复】使用相同的HWC格式处理
        int h = fp16_img.rows, w = fp16_img.cols;
        int total_elements = h * w * 3;
        
        // BGR->RGB转换
        cv::Mat rgb_fp16_img;
        cv::cvtColor(fp16_img, rgb_fp16_img, cv::COLOR_BGR2RGB);
        
        // 确保数据连续性
        if (!rgb_fp16_img.isContinuous()) {
            rgb_fp16_img = rgb_fp16_img.clone();
        }
        
        // 调整静态缓冲区大小并直接复制HWC数据
        hwc_buffer.resize(total_elements);
        uint16_t* hwc_data = hwc_buffer.data();
        
        printf("🔄 使用静态缓冲区存储HWC格式数据，总元素=%d\n", total_elements);
        printf("  数据布局: HWC (Height=%d, Width=%d, Channels=3)\n", h, w);
        
        // 直接复制HWC格式的数据
        memcpy(hwc_data, rgb_fp16_img.data, total_elements * sizeof(uint16_t));
        
        // 创建包装静态缓冲区的Mat
        processed_img = cv::Mat(h, w, CV_16FC3, hwc_data);
        
        printf("✅ HWC数据复制完成: 总元素=%d, 内存大小=%zu bytes\n", 
               total_elements, hwc_buffer.size() * sizeof(uint16_t));
        inputs[0].buf = hwc_buffer.data();  // 直接使用静态缓冲区
        
        printf("直接处理(FP16-HWC): 原尺寸=%dx%dx%d, HWC张量总元素=%d, 数据类型=%d, 连续性=%s\n", 
               height, width, channel, (int)processed_img.total(),
               processed_img.type(), processed_img.isContinuous() ? "是" : "否");
    }

    // 检查输入数据是否有效
    if (inputs[0].buf == nullptr)
    {
        std::cerr << "输入数据为空" << std::endl;
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }

    // 【关键验证】检查输入数据完整性，避免段错误
    printf("🔍 最终输入验证:\n");
    printf("  静态缓冲区指针: %p\n", hwc_buffer.data());
    printf("  输入缓冲区指针: %p\n", inputs[0].buf);
    printf("  期望数据大小: %d bytes\n", inputs[0].size);
    printf("  静态缓冲区大小: %zu bytes\n", hwc_buffer.size() * sizeof(uint16_t));
    printf("  指针一致性: %s\n", (inputs[0].buf == hwc_buffer.data()) ? "✅ 一致" : "❌ 不一致");
    printf("  数据类型匹配: %s\n", (inputs[0].type == RKNN_TENSOR_FLOAT16) ? "✅ FP16" : "❌ 不匹配");
    
    // 验证数据大小匹配
    size_t expected_size = width * height * channel * sizeof(uint16_t);
    size_t actual_size = hwc_buffer.size() * sizeof(uint16_t);
    
    if (actual_size != expected_size) {
        printf("❌ 严重错误：数据大小不匹配！期望=%zu, 实际=%zu\n", expected_size, actual_size);
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }
    
    // 检查缓冲区数据有效性（前几个值）
    if (hwc_buffer.size() >= 4) {
        printf("  静态缓冲区前4个FP16值: 0x%04x 0x%04x 0x%04x 0x%04x\n",
               hwc_buffer[0], hwc_buffer[1], hwc_buffer[2], hwc_buffer[3]);
    }
    
    printf("✅ 输入数据验证通过，使用静态缓冲区设置模型输入...\n");
    
    // 【最终安全检查】在调用RKNN API前进行内存边界检查
    if (hwc_buffer.empty() || hwc_buffer.data() == nullptr) {
        printf("❌ 致命错误：静态缓冲区为空或无效！\n");
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }
    
    // 额外的内存访问测试
    try {
        volatile uint16_t test_access = hwc_buffer[0];
        volatile uint16_t test_access_last = hwc_buffer[hwc_buffer.size()-1];
        printf("✅ 内存访问测试通过：首元素=0x%04x, 末元素=0x%04x\n", 
               test_access, test_access_last);
    } catch (...) {
        printf("❌ 内存访问测试失败，缓冲区可能无效\n");
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }
    
    // 将处理后的图像数据设置为模型输入
    printf("🚀 调用 rknn_inputs_set...\n");
    ret = rknn_inputs_set(ctx, io_num.n_input, inputs);
    if (ret < 0)
    {
        printf("❌ 设置模型输入失败: %d\n", ret);
        std::cerr << "可能的原因：数据格式不匹配或内存错误" << std::endl;
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }

    // 初始化输出结构体，指定输出数据为FP16格式
    rknn_output outputs[io_num.n_output];
    memset(outputs, 0, sizeof(outputs));
    for (uint32_t i = 0; i < io_num.n_output; i++)
    {
        outputs[i].want_float = 0;  // 保持为0，让RKNN返回原始FP16数据
    }
    printf("✅ 模型输入设置成功，输入尺寸: height=%d, width=%d, channel=%d\n", height, width, channel);
    
    // 模型推理
    printf("🚀 开始RKNN模型推理...\n");
    ret = rknn_run(ctx, NULL);
    if (ret < 0)
    {
        printf("❌ 模型推理失败: %d\n", ret);
        std::cerr << "推理失败可能原因：输入数据格式错误或模型不兼容" << std::endl;
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }
    
    printf("✅ 模型推理成功，获取输出结果...\n");

    ret = rknn_outputs_get(ctx, io_num.n_output, outputs, NULL);
    if (ret < 0)
    {
        std::cerr << "获取模型输出失败: " << ret << std::endl;
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }

    // 后处理/Post-processing
    DetectionResultsGroup detect_result_group;

    // 对于FP16输出，不需要量化和反量化参数
    std::vector<float> out_scales;
    std::vector<int32_t> out_zps;
    for (uint32_t i = 0; i < io_num.n_output; ++i)
    {
        out_scales.push_back(1.0f);  // FP16不需要缩放
        out_zps.push_back(0);        // FP16不需要零点
    }

    // 检查输出数据是否有效
    if (outputs[0].buf == nullptr)
    {
        std::cerr << "模型输出数据为空" << std::endl;
        ret = rknn_outputs_release(ctx, io_num.n_output, outputs);
        DetectionResultsGroup empty_result;
        empty_result.cur_img = orig_img.clone();
        empty_result.cur_frame_id = cur_frame_id;
        empty_result.fps = 0.0f;
        return empty_result;
    }

    // 【增强调试】检查模型输出数据的有效性
    for (uint32_t i = 0; i < io_num.n_output; i++) {
        printf("=== 输出 %d 信息 ===\n", i);
        printf("  维度: [");
        for (uint32_t j = 0; j < output_attrs[i].n_dims; j++) {
            printf("%d", output_attrs[i].dims[j]);
            if (j < output_attrs[i].n_dims - 1) printf(", ");
        }
        printf("]\n");
        printf("  数据大小: %d bytes\n", outputs[i].size);
        printf("  数据类型: %d, 格式: %d\n", output_attrs[i].type, output_attrs[i].fmt);
        
        // 检查输出数据的前几个值
        if (outputs[i].buf != nullptr && outputs[i].size >= 8) {
            uint16_t* data_fp16 = (uint16_t*)outputs[i].buf;
            printf("  前4个FP16原始值: 0x%04x 0x%04x 0x%04x 0x%04x\n", 
                   data_fp16[0], data_fp16[1], data_fp16[2], data_fp16[3]);
            
            // 转换为浮点数查看
            printf("  对应浮点值: %.6f %.6f %.6f %.6f\n",
                   fp16_to_fp32(data_fp16[0]), fp16_to_fp32(data_fp16[1]),
                   fp16_to_fp32(data_fp16[2]), fp16_to_fp32(data_fp16[3]));
        }
    }

    // 执行后处理
    if (io_num.n_output == 1)
    {
        // YOLOv8单输出 - 传递FP16数据
        printf("执行YOLOv8单输出后处理（FP16格式）\n");
        post_process_yolov8((uint16_t *)outputs[0].buf, height, width, box_conf_threshold, nms_threshold, pads, scale_w,
        scale_h, out_zps, out_scales, &detect_result_group,
        output_attrs[0].n_dims, output_attrs[0].dims);
    }
    else if (io_num.n_output == 3)
    {
        // YOLOv5三输出
        if (outputs[1].buf != nullptr && outputs[2].buf != nullptr)
        {
            // post_process((int8_t *)outputs[0].buf, (int8_t *)outputs[1].buf, (int8_t *)outputs[2].buf, height, width,
            //              box_conf_threshold, nms_threshold, pads, scale_w, scale_h, out_zps, out_scales,
            //              &detect_result_group);
            std::cerr << "YOLOv5临时不处理" << std::endl;
        }
        else
        {
            std::cerr << "YOLOv5输出数据不完整" << std::endl;
        }
    }
    else
    {
        std::cerr << "不支持的输出数量: " << io_num.n_output << std::endl;
    }

    // 添加帧ID和原始图像到结果中
    detect_result_group.cur_frame_id = cur_frame_id;
    detect_result_group.cur_img = orig_img.clone();

    ret = rknn_outputs_release(ctx, io_num.n_output, outputs);

    return detect_result_group;
}

RkPt::~RkPt()
{
    ret = rknn_destroy(ctx);

    if (model_data)
        free(model_data);

    if (input_attrs)
        free(input_attrs);
    if (output_attrs)
        free(output_attrs);
}
